package com.ruoyi.system.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.ObjectId;
import cn.hutool.core.util.StrUtil;
import com.alibaba.csp.sentinel.util.AssertUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.ruoyi.common.core.constant.UserConstants;
import com.ruoyi.common.core.enums.BMIndexEnum;
import com.ruoyi.common.core.enums.BMPayObjectTypeEnum;
import com.ruoyi.common.core.enums.ContestAuditStatusEnum;
import com.ruoyi.common.core.enums.PaymentStatusEnum;
import com.ruoyi.common.core.exception.ServiceException;
import com.ruoyi.common.core.utils.CommonStreamUtil;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.StringUtils;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.service.TokenService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.domain.SysUser;
import com.ruoyi.system.api.model.LoginUser;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.bm.*;
import com.ruoyi.system.domain.bm.dto.CoachOrPlayerAuditDTO;
import com.ruoyi.system.domain.bm.dto.CoachOrPlayerListDTO;
import com.ruoyi.system.domain.bm.dto.CoachOrPlayerListReturnDTO;
import com.ruoyi.system.domain.bm.dto.GetOrderStatusDTO;
import com.ruoyi.system.domain.dto.H5.NewContestListDto;
import com.ruoyi.system.domain.dto.Web.ContestBindingDto;
import com.ruoyi.system.domain.vo.H5.NewContestListVO;
import com.ruoyi.system.mapper.*;
import com.ruoyi.system.mapper.bm.*;
import com.ruoyi.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

import static com.ruoyi.common.core.constant.WxPayConstant.WX_PAYMENT_OUT_TRADE_PREFIX;

/**
 * 联赛Service业务层处理
 *
 * @author wangbj
 * @date 2024-04-16
 */
@Slf4j
@Service
public class BaseContestServiceImpl extends ServiceImpl<BaseContestMapper, BaseContest> implements IBaseContestService {
    @Resource
    private BaseContestMapper baseContestMapper;
    @Resource
    private IBaseTournamentPersonnelService iBaseTournamentPersonnelService;

    @Resource
    LoginUserSetUtil loginUserSetUtil;

    @Resource
    private IBaseUserOrganizationService iBaseUserOrganizationService;

    @Resource
    RedisService redisService;

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private BaseContestBindingMapper baseContestBindingMapper;

    @Resource
    TokenService tokenService;

    @Resource
    private BMTeamMapper bmTeamMapper;

    @Resource
    private BMCoachMapper bmCoachMapper;

    @Resource
    private BMPlayerMapper bmPlayerMapper;

    @Resource
    private BaseWxPayService wxPayService;

    @Resource
    private WxPayProperties wxPayProperties;

    @Resource
    private BMPaymentMapper bmPaymentMapper;
    @Resource
    private BaseBasketballTeamMapper baseBasketballTeamMapper;
    @Resource
    private BaseAreasMapper baseAreasMapper;

    @Resource
    private BaseCoachMapper baseCoachMapper;
    @Resource
    private BasketballPlayerAndTeamMapper basketballPlayerAndTeamMapper;

    @Resource
    private BaseBasketballPlayerMapper baseBasketballPlayerMapper;
    @Resource
    private BMPackMapper bmPackMapper;
    @Resource
    private BaseContestBindingGroupMapper baseContestBindingGroupMapper;
    @Resource
    private BaseTournamentMapper baseTournamentMapper;


    public final static String CONTEST_PREFIX_ID = "basketball:contest:id:";


    /**
     * 查询联赛
     *
     * @param id 联赛主键
     * @return 联赛
     */
    @Override
    public BaseContest selectBaseContestById(Long id) {
        return baseContestMapper.selectBaseContestById(id);
    }

    /**
     * 查询联赛列表
     *
     * @param baseContest 联赛
     * @return 联赛
     */
    @Override
    public List<BaseContest> selectBaseContestList(BaseContest baseContest) {
        if (Objects.equals(SecurityUtils.getUserId(), 171481617989977966L)) {
            return baseContestMapper.selectList(Wrappers.<BaseContest>lambdaQuery()
                    .like(StringUtils.isNotEmpty(baseContest.getContestName()), BaseContest::getContestName, baseContest.getContestName())
            );
        }

        List<BaseUserOrganization> list = iBaseUserOrganizationService.getUserId(SecurityUtils.getUserId());
        if (CollUtil.isEmpty(list)) {
            return CollUtil.newArrayList();
        }
        List<BaseTournamentPersonnel> list1 = iBaseTournamentPersonnelService.list(Wrappers.<BaseTournamentPersonnel>lambdaQuery()
                .in(BaseTournamentPersonnel::getUserId, SecurityUtils.getUserId()));
        List<Long> collect1 = list1.stream().map(BaseTournamentPersonnel::getContestId).collect(Collectors.toList());
        if (CollUtil.isEmpty(collect1)) {
            return CollUtil.newArrayList();
        }
        Set<Long> collect = list.stream().map(BaseUserOrganization::getOrganizationId).collect(Collectors.toSet());
        List<BaseContest> baseContests = baseContestMapper.selectList(Wrappers.<BaseContest>lambdaQuery()
                .in(BaseContest::getOrganizationId, collect)
                .like(StringUtils.isNotEmpty(baseContest.getContestName()), BaseContest::getContestName, baseContest.getContestName())
                .in(BaseContest::getId, collect1)
        );

        return baseContests;
    }

    /**
     * 新增联赛
     *
     * @param baseContest 联赛
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseContest insertBaseContest(BaseContest baseContest) {
        checkContestName(baseContest.getContestName());
        baseContest.setCreateTime(DateUtils.getNowDate());
        baseContest.setCreateUserId(SecurityUtils.getUserId());
        baseContest.setAuditStatus(ContestAuditStatusEnum.AUDIT.getCode());
        int i = baseContestMapper.insert(baseContest);


        iBaseTournamentPersonnelService.save(BaseTournamentPersonnel.builder()
                .userId(SecurityUtils.getUserId())
                .type(6L)
                .level(0L)
                .organizationId(baseContest.getOrganizationId())
                .contestId(baseContest.getId())
                .build());
        BaseContest contest = baseContestMapper.selectBaseContestList(baseContest).get(0);
        redisService.setCacheObject(CONTEST_PREFIX_ID.concat(contest.getId().toString()), baseContest);

        iBaseUserOrganizationService.savePO(baseContest.getOrganizationId(), SecurityUtils.getUserId());
        return contest;
    }

    private void checkContestName(String contestName) {
        List<BaseContest> list = this.list(Wrappers.<BaseContest>lambdaQuery().eq(BaseContest::getContestName, contestName).eq(BaseContest::getIsDeleted, 0));
        if (CollUtil.isNotEmpty(list)) {
            throw new RuntimeException("联赛名称已经存在");
        }
    }

    /**
     * 修改联赛
     *
     * @param baseContest 联赛
     * @return 结果
     */
    @Override
    public int updateBaseContest(BaseContest baseContest) {
        loginUserSetUtil.populateFields(baseContest, 2);
        int i = baseContestMapper.updateBaseContest(baseContest);
        redisService.setCacheObject(CONTEST_PREFIX_ID.concat(baseContest.getId().toString()), baseMapper.selectBaseContestById(baseContest.getId()));
        return i;
    }

    /**
     * 批量删除联赛
     *
     * @param ids 需要删除的联赛主键
     * @return 结果
     */
    @Override
    public int deleteBaseContestByIds(Long[] ids) {
        for (int i = 0; i < ids.length; i++) {
            redisService.deleteObject(CONTEST_PREFIX_ID.concat(ids[i].toString()));
        }
        return baseContestMapper.deleteBaseContestByIds(ids);
    }

    /**
     * 删除联赛信息
     *
     * @param id 联赛主键
     * @return 结果
     */
    @Override
    public int deleteBaseContestById(Long id) {

        redisService.deleteObject(CONTEST_PREFIX_ID.concat(id.toString()));
        return baseContestMapper.deleteBaseContestById(id);
    }

    @Override
    public List<BaseContest> gerMyList(Long userid) {
        return baseContestMapper.getMyList(userid);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int auditStatus(BaseContest baseContest) {
        AssertUtil.notNull(baseContest.getId(), "联赛id不能为空");
        AssertUtil.notNull(baseContest.getAuditStatus(), "联赛审核状态不能为空");
        BaseContest byId = this.getById(baseContest.getId());
        AssertUtil.notNull(byId, "联赛异常!");

        LambdaUpdateWrapper<BaseContest> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(BaseContest::getAuditStatus, baseContest.getAuditStatus());
        updateWrapper.set(Objects.nonNull(baseContest.getTournamentNum()), BaseContest::getTournamentNum, baseContest.getTournamentNum());
        updateWrapper.eq(BaseContest::getId, baseContest.getId());
        //审核通过 主账号也需要联赛权限
        if (Objects.equals(baseContest.getAuditStatus(), 1)) {
            //主账号
            iBaseTournamentPersonnelService.save(BaseTournamentPersonnel.builder()
                    .userId(UserConstants.USER_ID)
                    .type(6L)
                    .level(0L)
                    .organizationId(byId.getOrganizationId())
                    .contestId(baseContest.getId())
                    .build());
            iBaseUserOrganizationService.savePO(byId.getOrganizationId(), SecurityUtils.getUserId());
        }
        return update(updateWrapper) ? 1 : 0;
    }

    @Override
    public List<BaseContest> selectList(BaseContest baseContest) {

        List<BaseContest> baseContests = baseContestMapper.selectList(Wrappers.<BaseContest>lambdaQuery()
                .like(StrUtil.isNotBlank(baseContest.getContestName()), BaseContest::getContestName, baseContest.getContestName())
                .ge(Objects.nonNull(baseContest.getStartTime()), BaseContest::getContestBeginTime, baseContest.getStartTime())
                .le(Objects.nonNull(baseContest.getEndTime()), BaseContest::getContestBeginTime, baseContest.getEndTime())
                .eq(Objects.nonNull(baseContest.getAuditStatus()), BaseContest::getAuditStatus, baseContest.getAuditStatus())
                .ne(Objects.nonNull(baseContest.getId()), BaseContest::getId, baseContest.getId())
                .in(CollUtil.isNotEmpty(baseContest.getIds()), BaseContest::getId, baseContest.getIds())
                .orderByDesc(BaseContest::getContestBeginTime)
        );
        if (CollUtil.isEmpty(baseContests)) {
            return new ArrayList<>();
        }
        List<Long> userIds = baseContests.stream().map(BaseContest::getCreateUserId).collect(Collectors.toList());
        List<SysUser> sysUsers = sysUserMapper.selectUserByIds(userIds);
        Map<Long, SysUser> userMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, Function.identity()));

        baseContests.forEach(o -> {
            if (userMap.containsKey(o.getCreateUserId())) {
                SysUser sysUser = userMap.get(o.getCreateUserId());
                o.setPhone(sysUser.getPhonenumber());
            }
        });
        return baseContests;
    }

    @Override
    public int saveImg(BaseContest baseContest) {
        AssertUtil.notNull(baseContest.getId(), "联赛id不能为空");
        BaseContest byId = getById(baseContest.getId());
        AssertUtil.notNull(byId, "联赛不存在");
        return updateById(baseContest) ? 1 : 0;
    }

    @Override
    public List<BaseContest> getContestBinding(BaseContest baseContest) {
        List<BaseContest> baseContests = baseContestMapper.selectList(Wrappers.<BaseContest>lambdaQuery()
                .like(StrUtil.isNotBlank(baseContest.getContestName()), BaseContest::getContestName, baseContest.getContestName())
                .ne(Objects.nonNull(baseContest.getId()), BaseContest::getId, baseContest.getId())
                .orderByDesc(BaseContest::getContestBeginTime)
        );
        List<BaseContestBinding> baseContestBindings = baseContestBindingMapper.selectListById(baseContest.getId());
        if (CollUtil.isEmpty(baseContestBindings)) {
            return baseContests;
        }
        Set<Long> longs = CommonStreamUtil.transSet(baseContestBindings, BaseContestBinding::getContestBindingId);
        longs.addAll(CommonStreamUtil.transSet(baseContestBindings, BaseContestBinding::getContestId));
        baseContests.forEach(item -> {
            if (longs.contains(item.getId())) {
                item.setContestFlag(1);
            }
        });
        return baseContests;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int contestBinding(ContestBindingDto contestBindingDto) {
        AssertUtil.notNull(contestBindingDto.getId(), "指定绑定id不能为空");

        List<BaseContestBinding> baseContestBindings = baseContestBindingMapper.selectListById(contestBindingDto.getId());
        if (CollUtil.isNotEmpty(baseContestBindings)) {
            baseContestBindingMapper.deleteBatchIds(baseContestBindings);
        }
        contestBindingDto.getIds().forEach(item -> {
            BaseContestBinding contestBinding = new BaseContestBinding();
            contestBinding.setContestId(contestBindingDto.getId());
            contestBinding.setContestBindingId(item);
            baseContestBindingMapper.insert(contestBinding);
        });
        return 1;
    }

    @Override
    public List<BMTeam> myTeam(Integer indexId) {
        LoginUser loginUser = tokenService.getLoginUser();
        if (Objects.isNull(loginUser)) {
            throw new RuntimeException("请先登录");
        }
        List<Long> contestId = BMIndexEnum.getValue(indexId);
        if (CollUtil.isEmpty(contestId)) {
            return new ArrayList<>();
        }
        Long userid = loginUser.getUserid();
        SysUser sysUser = sysUserMapper.selectUserById(userid);
        //用手机号获取绑定
        List<BMPlayer> bmPlayers = bmPlayerMapper.selectByPhone(sysUser.getPhonenumber(), null, contestId);
        List<BMCoach> coachList = bmCoachMapper.selectByPhone(sysUser.getPhonenumber(), null, contestId);
        Set<Long> teamIds = new HashSet<>();
        teamIds.addAll(CommonStreamUtil.transSet(bmPlayers, BMPlayer::getTeamId));
        teamIds.addAll(CommonStreamUtil.transSet(coachList, BMCoach::getTeamId));
        List<BMTeam> bmTeams = new ArrayList<>();
        if (CollUtil.isNotEmpty(teamIds)) {
            bmTeams = bmTeamMapper.selectBatchIds(teamIds);
        }
        //领队球队
        List<BMTeam> bmTeams1 = bmTeamMapper.selectByUserId(userid);
        List<BMTeam> combinedList = Stream.concat(bmTeams.stream(), bmTeams1.stream())
                .distinct()
                .collect(Collectors.toList());
        return combinedList;
    }

    @Override
    public List<BMCoach> coachList(Long teamId) {
        List<BMCoach> bmCoaches = bmCoachMapper.coachListByTeamId(teamId);
        if (CollUtil.isEmpty(bmCoaches)) {
            return new ArrayList<>();
        }
        Set<Long> ids = CommonStreamUtil.transSet(bmCoaches, BMCoach::getId);
        List<BMPayment> bmPayments = bmPaymentMapper.selectByObjectIds(BMPayObjectTypeEnum.COACH.getCode(), ids);
        Map<Long, BMPayment> longBMPaymentMap = CommonStreamUtil.toMap(bmPayments, BMPayment::getObjectId);

        List<BMCoach> coachList = new ArrayList<>();
        bmCoaches.forEach(bo -> {
            if (longBMPaymentMap.containsKey(bo.getId())) {
                BMPayment bmPayment = longBMPaymentMap.get(bo.getId());
                if (Objects.equals(bmPayment.getPaymentStatus(), PaymentStatusEnum.REFUND_PAID.getId())) {
                    return;
                }
                bo.setPaymentStatus(bmPayment.getPaymentStatus());
            }
            coachList.add(bo);
        });
        return coachList;
    }

    @Override
    public List<BMPlayer> playerList(Long teamId) {
        List<BMPlayer> bmPlayers = bmPlayerMapper.playerListByTeamId(teamId);
        if (CollUtil.isEmpty(bmPlayers)) {
            return new ArrayList<>();
        }
        Set<Long> ids = CommonStreamUtil.transSet(bmPlayers, BMPlayer::getId);
        List<BMPayment> bmPayments = bmPaymentMapper.selectByObjectIds(BMPayObjectTypeEnum.PLAYER.getCode(), ids);
        Map<Long, BMPayment> longBMPaymentMap = CommonStreamUtil.toMap(bmPayments, BMPayment::getObjectId);

        List<BMPlayer> playerList = new ArrayList<>();
        bmPlayers.forEach(bo -> {
            if (longBMPaymentMap.containsKey(bo.getId())) {
                BMPayment bmPayment = longBMPaymentMap.get(bo.getId());
                if (Objects.equals(bmPayment.getPaymentStatus(), PaymentStatusEnum.REFUND_PAID.getId())) {
                    return;
                }
                bo.setPaymentStatus(bmPayment.getPaymentStatus());
            }
            playerList.add(bo);
        });
        return playerList;
    }

    @Override
    public BMTeam createTeam(BMTeam team) {
        AssertUtil.notNull(team.getContestId(), "联赛id不能为空");
        AssertUtil.notNull(team.getName(), "名称不能为空");
        AssertUtil.notNull(team.getLogo(), "球队logo不能为空");
        AssertUtil.notNull(team.getPhone(), "联系电话不能为空");
        BMTeam bmTeam = bmTeamMapper.selectByName(team.getName(), team.getContestId());
        if (Objects.nonNull(bmTeam)) {
            throw new RuntimeException("球队名称已存在");
        }
        LoginUser loginUser = tokenService.getLoginUser();
        team.setUserId(loginUser.getUserid());
        team.setCreateTime(new Date());
        int insert = bmTeamMapper.insert(team);
        return team;
    }

    @Override
    public BMTeam editTeam(BMTeam team) {
        AssertUtil.notNull(team.getId(), "id不能为空");
        BMTeam bmTeam1 = bmTeamMapper.selectById(team.getId());

        BMTeam bmTeam = bmTeamMapper.selectByName(team.getName(),bmTeam1.getContestId());
        if (Objects.nonNull(bmTeam) && !Objects.equals(team.getId(), bmTeam.getId())) {
            throw new RuntimeException("球队名称已存在");
        }

        LoginUser loginUser = tokenService.getLoginUser();
        team.setUpdateBy(loginUser.getUsername());
        team.setUpdateTime(new Date());
        bmTeamMapper.updateById(team);
        return team;
    }

    @Override
    public BMTeam teamDetail(Long teamId) {
        return bmTeamMapper.selectById(teamId);
    }

    @Override
    public WxPayUnifiedOrderV3Result.JsapiResult createCoach(BMCoach coach) {
        BaseContest contest = baseContestMapper.selectById(coach.getContestId());
        if (Objects.isNull(contest)) {
            throw new RuntimeException("联赛信息异常");
        }
        //当前时间必须在报名时间内
        if (contest.getSignStartTime().after(new Date()) || contest.getSignEndTime().before(new Date())) {
            throw new RuntimeException("当前时间不在报名时间段内");
        }
        BMPayment payment;
        if (Objects.isNull(coach.getId())) {
            AssertUtil.notNull(coach.getContestId(), "联赛不能为空");
            AssertUtil.notNull(coach.getTeamId(), "球队不能为空");
            AssertUtil.notNull(coach.getName(), "名称不能为空");
            AssertUtil.notNull(coach.getPhone(), "联系电话不能为空");
            AssertUtil.notNull(coach.getCard(), "证件号不能为空");
            AssertUtil.notNull(coach.getLogo(), "图片不能为空");
//            AssertUtil.notNull(coach.getAmount(), "报名金额不能为空");
            List<BMCoach> phoneCoach = bmCoachMapper.selectByPhone(coach.getPhone(), coach.getTeamId(), new ArrayList<>());
            if (CollUtil.isNotEmpty(phoneCoach)) {
                throw new RuntimeException("当前手机号,已存在教练身份");
            }
            coach.setType(1);
            coach.setAddFlag(0);
            List<BMCoach> bmCoaches = bmCoachMapper.coachListByTeamId(coach.getTeamId());
            if (CollUtil.isEmpty(bmCoaches)) {
                coach.setType(0);
            }

            bmCoachMapper.insert(coach);

            LoginUser loginUser = tokenService.getLoginUser();
            log.info("用户id,{}", loginUser.getUserid());
            SysUser sysUser = sysUserMapper.selectUserById(loginUser.getUserid());

            if (Objects.isNull(coach.getAmount()) || coach.getAmount().compareTo(BigDecimal.ZERO) == 0) {
                //创建pay支付表
                payment = new BMPayment();
                payment.setObjectId(coach.getId());
                payment.setObjectType(BMPayObjectTypeEnum.COACH.getCode());
                payment.setPaymentStatus(PaymentStatusEnum.PAID.getId());
                payment.setPaymentMethod(0);
                payment.setOutOrderSn(WX_PAYMENT_OUT_TRADE_PREFIX + ObjectId.next());
                payment.setBody(BMPayObjectTypeEnum.COACH.getInfo() + "报名费");
                payment.setAmount(coach.getAmount());
                payment.setOpenId(sysUser.getOpenId());
                payment.setIndexId(coach.getIndexId());
                bmPaymentMapper.insert(payment);
                return null;
            }
            //创建pay支付表
            payment = new BMPayment();
            payment.setObjectId(coach.getId());
            payment.setObjectType(BMPayObjectTypeEnum.COACH.getCode());
            payment.setPaymentStatus(PaymentStatusEnum.WAITING_PAY.getId());
            payment.setPaymentMethod(0);
            payment.setOutOrderSn(WX_PAYMENT_OUT_TRADE_PREFIX + ObjectId.next());
            payment.setBody(BMPayObjectTypeEnum.COACH.getInfo() + "报名费");
            payment.setAmount(coach.getAmount());
            payment.setOpenId(sysUser.getOpenId());
            payment.setIndexId(coach.getIndexId());
            bmPaymentMapper.insert(payment);
        } else {
            payment = bmPaymentMapper.selectByObjectId(coach.getId(), BMPayObjectTypeEnum.COACH.getCode());
        }
        //不支付
        if (Objects.equals(coach.getPayType(), 0)) {
            return null;
        }
        WxPayUnifiedOrderV3Result.JsapiResult wxOrder = wxPayService.createWxPayUnifiedOrder(payment.getId());
        return wxOrder;
    }


    @Override
    public WxPayUnifiedOrderV3Result.JsapiResult createPlayer(BMPlayer player) {
        BaseContest contest = baseContestMapper.selectById(player.getContestId());
        if (Objects.isNull(contest)) {
            throw new RuntimeException("联赛信息异常");
        }
        //当前时间必须在报名时间内
        if (contest.getSignStartTime().after(new Date()) || contest.getSignEndTime().before(new Date())) {
            throw new RuntimeException("当前时间不在报名时间段内");
        }

//        List<BMPlayer> bmPlayers = bmPlayerMapper.playerListByTeamId(player.getTeamId());
//        if (bmPlayers.size() >= contest.getMaxNum()){
//            throw new RuntimeException("当前球队已满员");
//        }
        LoginUser loginUser = tokenService.getLoginUser();
        log.info("用户id,{}", loginUser.getUserid());
        SysUser sysUser = sysUserMapper.selectUserById(loginUser.getUserid());
        BMPayment payment;
        if (Objects.isNull(player.getId())) {
            AssertUtil.notNull(player.getContestId(), "联赛不能为空");
            AssertUtil.notNull(player.getTeamId(), "球队不能为空");
            AssertUtil.notNull(player.getName(), "名称不能为空");
            AssertUtil.notNull(player.getCard(), "证件号不能为空");
            AssertUtil.notNull(player.getLogo(), "图片不能为空");
            AssertUtil.notNull(player.getAmount(), "报名金额不能为空");
//            AssertUtil.notNull(player.getEmergencyPhone(), "紧急联系人不能为空");
//            AssertUtil.notNull(player.getEmergencyStr(), "紧急联系人类型不能为空");
            AssertUtil.notNull(player.getPhone(), "手机号码不能为空");
            List<BMPlayer> phoneCoach = bmPlayerMapper.selectByPhone(player.getPhone(), player.getTeamId(), new ArrayList<>());
            if (CollUtil.isNotEmpty(phoneCoach)) {
                throw new RuntimeException("当前手机号,已存在球员身份");
            }
            player.setAddFlag(0);
            bmPlayerMapper.insert(player);


            //创建pay支付表
            payment = new BMPayment();
            payment.setObjectId(player.getId());
            payment.setObjectType(BMPayObjectTypeEnum.PLAYER.getCode());
            payment.setPaymentStatus(PaymentStatusEnum.WAITING_PAY.getId());
            payment.setPaymentMethod(0);
            payment.setOutOrderSn(WX_PAYMENT_OUT_TRADE_PREFIX + ObjectId.next());
            payment.setBody(BMPayObjectTypeEnum.PLAYER.getInfo() + "报名费");
            payment.setAmount(player.getAmount());
            payment.setOpenId(sysUser.getOpenId());
            payment.setIndexId(player.getIndexId());
            bmPaymentMapper.insert(payment);
        } else {
            payment = bmPaymentMapper.selectByObjectId(player.getId(), BMPayObjectTypeEnum.PLAYER.getCode());
            payment.setOutOrderSn(WX_PAYMENT_OUT_TRADE_PREFIX + ObjectId.next());
            payment.setOpenId(sysUser.getOpenId());
            bmPaymentMapper.updateById( payment);
        }

        //不支付
        if (Objects.equals(player.getPayType(), 0)) {
            return null;
        }
        WxPayUnifiedOrderV3Result.JsapiResult wxOrder = wxPayService.createWxPayUnifiedOrder(payment.getId());
        return wxOrder;
    }

    @Override
    public BMPayment getOrderStatus(GetOrderStatusDTO param) {
        BMPayment payment = bmPaymentMapper.selectByObjectId(param.getId(), param.getType());
        return payment;
    }

    @Override
    public List<CoachOrPlayerListReturnDTO> coachOrPlayerList(CoachOrPlayerListDTO dto) {
        List<CoachOrPlayerListReturnDTO> coachOrPlayerListReturnDTOS;
        if (Objects.equals(dto.getType(), 0)) {
            coachOrPlayerListReturnDTOS = bmCoachMapper.selectByPaymentStatus(dto);
        } else {
            coachOrPlayerListReturnDTOS = bmPlayerMapper.selectByPaymentStatus(dto);
        }
        BMPack bmPack = new BMPack();
        bmPack.setContestIds(dto.getContestIds());
        if (StringUtils.isNotEmpty(dto.getContestId())) {
            bmPack.setContestId(Long.valueOf(dto.getContestId()));
        }
        List<BMPack> bmPacks = bmPackMapper.selectByList(bmPack);
        Map<Long, BMPack> packMap = CommonStreamUtil.toMap(bmPacks, BMPack::getId);

        coachOrPlayerListReturnDTOS.forEach(bo -> {
            if (StringUtils.isNotEmpty(bo.getPackId())) {
                String[] split = bo.getPackId().split(",");
                List<String> packName = new ArrayList<>();
                Arrays.stream(split).forEach(pack -> {
                    if (packMap.containsKey(Long.valueOf(pack))) {
                        packName.add(packMap.get(Long.valueOf(pack)).getName());
                    }
                });
                bo.setGiftName(packName);
            }
            bo.setAuditStatusName(Objects.equals(bo.getAuditStatus(), 0) ? "未通过" : "已通过");
            bo.setPaymentStatusName(PaymentStatusEnum.isExistById(bo.getPaymentStatus()).getName());
        });
        return coachOrPlayerListReturnDTOS;
    }

    @Override
    public int deleteCoach(Long id) {
        return bmCoachMapper.deleteById(id);
    }

    @Override
    public int deletePlayer(Long id) {
        return bmPlayerMapper.deleteById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String coachOrPlayerAudit(CoachOrPlayerAuditDTO param) {
        if (Objects.equals(param.getType(), 0)) {
            coachAudit(param);
        } else {
            playerAudit(param);
        }
        return "审批通过";
    }


    @Override
    public List<BaseArea> provinceList() {
        return baseAreasMapper.provinceList();
    }

    @Override
    public List<BaseContestBindingGroup> getContestBindingGroupList() {
        return baseContestBindingGroupMapper.selectList(Wrappers.<BaseContestBindingGroup>lambdaQuery().eq(BaseContestBindingGroup::getIsDeleted, 0L));
    }

    @Override
    public List<BaseContest> getContestBindingList(BaseContestBindingGroup contestBindingGroup) {
        AssertUtil.notNull(contestBindingGroup.getId(), "绑定组id不能为空");
        BaseContestBindingGroup baseContestBindingGroup = baseContestBindingGroupMapper.selectById(contestBindingGroup.getId());
        AssertUtil.notNull(baseContestBindingGroup, "绑定组不存在");
        List<BaseContestBinding> baseContestBindings = baseContestBindingMapper.selectByBindingGroupId(contestBindingGroup.getId());
        if (CollUtil.isEmpty(baseContestBindings)) {
            return new ArrayList<>();
        }
        return baseContestMapper.selectBatchIds(baseContestBindings.stream().map(BaseContestBinding::getContestId).collect(Collectors.toList()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteContestBindingGroup(Long id) {
        BaseContestBindingGroup baseContestBindingGroup = baseContestBindingGroupMapper.selectById(id);
        AssertUtil.notNull(baseContestBindingGroup, "绑定组不存在");
        baseContestBindingGroup.setIsDeleted(1L);
        baseContestBindingGroupMapper.updateById(baseContestBindingGroup);

        //删除绑定关系
        baseContestBindingMapper.delete(Wrappers.<BaseContestBinding>lambdaQuery().eq(BaseContestBinding::getContestBindingId, id));
        return 1;
    }

    @Override
    public int addContestBindingGroup(BaseContestBindingGroup baseContestBindingGroup) {
        AssertUtil.notNull(baseContestBindingGroup.getGroupName(), "绑定组名称不能为空");
        AssertUtil.notNull(baseContestBindingGroup.getGroupLogo(), "绑定组logo不能为空");
        return baseContestBindingGroupMapper.insert(baseContestBindingGroup);
    }

    @Override
    public int contestBindingNew(ContestBindingDto contestBindingDto) {
        AssertUtil.notNull(contestBindingDto.getId(), "指定绑定id不能为空");

        List<BaseContestBinding> baseContestBindings = baseContestBindingMapper.selectByBindingGroupId(contestBindingDto.getId());
        if (CollUtil.isNotEmpty(baseContestBindings)) {
            baseContestBindingMapper.deleteBatchIds(baseContestBindings);
        }
        contestBindingDto.getIds().forEach(item -> {
            BaseContestBinding contestBinding = new BaseContestBinding();
            contestBinding.setContestId(item);
            contestBinding.setContestBindingId(contestBindingDto.getId());
            baseContestBindingMapper.insert(contestBinding);
        });
        return 1;
    }

    @Override
    public WxPayUnifiedOrderV3Result.JsapiResult totalPlayerPay(BMTeam team) {
        AssertUtil.notNull(team.getId(), "球队id不能为空");
        BMTeam bmTeam = bmTeamMapper.selectById(team.getId());
        AssertUtil.notNull(bmTeam, "球队不存在");
        BaseContest baseContest = baseContestMapper.selectById(bmTeam.getContestId());
        AssertUtil.notNull(baseContest, "联赛异常！");
        AssertUtil.notNull(baseContest.getTotalExpenses(), "报名费用异常！");

        List<BMPlayer> playerList = bmPlayerMapper.playerListByTeamId(team.getId());
        if (CollUtil.isEmpty(playerList)){
            throw new ServiceException("请添加球员!");
        }
        Set<Long> playerIds = CommonStreamUtil.transSet(playerList, BMPlayer::getId);
        List<BMPayment> bmPayments = bmPaymentMapper.selectByObjectIds(BMPayObjectTypeEnum.PLAYER.getCode(), playerIds);

        //获取已支付
        List<BMPayment> paidPayList = CommonStreamUtil.filter(bmPayments,
                bo -> (bo.getPaymentStatus() == PaymentStatusEnum.PAID.getId() || bo.getPaymentStatus() == PaymentStatusEnum.REFUND_SUCCESS.getId()));
        //获取未支付
        List<BMPayment> paidNotPayList = CommonStreamUtil.filter(bmPayments, bo -> bo.getPaymentStatus() == PaymentStatusEnum.WAITING_PAY.getId());
        if (CollUtil.isEmpty(paidNotPayList)){
            throw new ServiceException("没有未支付球员");
        }
        BigDecimal payTotal = paidPayList.stream().map(BMPayment::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        //剩余代支付金额
        BigDecimal amount = baseContest.getTotalExpenses().subtract(payTotal);
        if (amount.compareTo(BigDecimal.ZERO) <= 0){
            throw new ServiceException("没有未支付球员");
        }
        LoginUser loginUser = tokenService.getLoginUser();
        log.info("用户id,{}", loginUser.getUserid());
        SysUser sysUser = sysUserMapper.selectUserById(loginUser.getUserid());

        BMPayment bmPayment = bmPaymentMapper.selectByObjectId(team.getId(), BMPayObjectTypeEnum.TEAM.getCode());
        if (Objects.nonNull(bmPayment)){
            bmPaymentMapper.deleteById(bmPayment);
        }
        //创建pay支付表
        BMPayment payment = new BMPayment();
        payment.setObjectId(team.getId());
        payment.setObjectType(BMPayObjectTypeEnum.TEAM.getCode());
        payment.setPaymentStatus(PaymentStatusEnum.WAITING_PAY.getId());
        payment.setPaymentMethod(0);
        payment.setOutOrderSn(WX_PAYMENT_OUT_TRADE_PREFIX + ObjectId.next());
        payment.setBody(BMPayObjectTypeEnum.TEAM.getInfo() + "报名费");
        payment.setAmount(amount);
        payment.setOpenId(sysUser.getOpenId());
        payment.setIndexId(team.getIndexId());
        bmPaymentMapper.insert(payment);

        WxPayUnifiedOrderV3Result.JsapiResult wxOrder = wxPayService.createWxPayUnifiedOrder(payment.getId());
        return wxOrder;
    }

    @Override
    public TableDataInfo newContestList(NewContestListDto dto) {
        List<BaseContest> baseContests = baseContestMapper.newContestList(dto);
        if (CollUtil.isEmpty(baseContests)) {
            return new TableDataInfo(new ArrayList<>(),0);
        }
        Set<Long> contestIds = CommonStreamUtil.transSet(baseContests, BaseContest::getId);
        List<BaseContestBinding> baseContestBindings = baseContestBindingMapper.selectByContestIds(contestIds);
        Map<Long, List<BaseContestBinding>> bindingMap = CommonStreamUtil.group(baseContestBindings, BaseContestBinding::getContestBindingId);


        List<NewContestListVO> newContestListVOList = new ArrayList<>();

        Set<Long> newContestIds = new HashSet<>();

        baseContests.forEach(item -> {
            if(newContestIds.contains(item.getId())){
                return;
            }
            NewContestListVO newContestListVO = new NewContestListVO();
            newContestListVO.setContestGroupType(1);

            List<BaseContestBinding> bindingList = baseContestBindings.stream().filter(binding -> Objects.equals(binding.getContestId(),item.getId())).collect(Collectors.toList());
            bindingList.forEach(binding -> {
                if(bindingMap.containsKey(binding.getContestBindingId())){
                    newContestListVO.setContestGroupType(0);
                    List<BaseContestBinding> baseContestBindings1 = bindingMap.get(binding.getContestBindingId());
                    newContestIds.addAll(CommonStreamUtil.transSet(baseContestBindings1, BaseContestBinding::getContestId));
                }
            });

            newContestListVO.setContestName(item.getContestName());
            newContestListVO.setId(item.getId());
            newContestListVO.setScoringWay(item.getScoringWay());
            newContestListVO.setContestLogo(item.getContestLogo());
            newContestListVOList.add(newContestListVO);
        });
        List<NewContestListVO> collect = newContestListVOList.stream()
                .skip((long) (dto.getPageNum() - 1) * dto.getPageSize())
                .limit(dto.getPageSize()).collect(Collectors.toList());

        if (CollUtil.isEmpty(collect)) {
            return new TableDataInfo(new ArrayList<>(),0);
        }

        Set<Long> contestIdList = CommonStreamUtil.transSet(collect, NewContestListVO::getId);
        List<BaseTournament> baseTournaments = baseTournamentMapper.selectByContestIds(contestIdList);
        Map<Long, BaseBasketballTeam> longBaseBasketballTeamMap = new HashMap<>();
        if (CollUtil.isNotEmpty(baseTournaments)){
            Set<Long> teamOneId = CommonStreamUtil.transSet(baseTournaments, BaseTournament::getTeamOneId);
            Set<Long> teamTwoId = CommonStreamUtil.transSet(baseTournaments, BaseTournament::getTeamTwoId);
            teamOneId.addAll(teamTwoId);
            List<BaseBasketballTeam> teamList = baseBasketballTeamMapper.selectBatchIds(teamOneId);
            longBaseBasketballTeamMap = CommonStreamUtil.toMap(teamList, BaseBasketballTeam::getId);
        }

        Map<Long, BaseBasketballTeam> finalLongBaseBasketballTeamMap = longBaseBasketballTeamMap;
        baseTournaments.forEach(item -> {
            if(finalLongBaseBasketballTeamMap.containsKey(item.getTeamOneId()) && finalLongBaseBasketballTeamMap.containsKey(item.getTeamTwoId())){
                BaseBasketballTeam teamOne = finalLongBaseBasketballTeamMap.get(item.getTeamOneId());
                BaseBasketballTeam teamTwo = finalLongBaseBasketballTeamMap.get(item.getTeamTwoId());
                item.setTournamentName(teamOne.getTeamName() + " VS " + teamTwo.getTeamName());
            }
        });
        Map<Long, List<BaseTournament>> tournamentContestIdMap = CommonStreamUtil.group(baseTournaments, BaseTournament::getContestId);


        collect.forEach(item -> {
            if(tournamentContestIdMap.containsKey(item.getId())){
                List<BaseTournament> baseTournamentList = tournamentContestIdMap.get(item.getId()).stream().limit(2).collect(Collectors.toList());

                List<NewContestListVO.TournamentListDto> tournamentList = new ArrayList<>();
                baseTournamentList.forEach(item1 -> {
                    NewContestListVO.TournamentListDto tournamentListDto = new NewContestListVO.TournamentListDto();

                    //主队客队
                    tournamentListDto.setTournamentName(item1.getTournamentName());
                    tournamentListDto.setTournamentId(item1.getId());
                    tournamentListDto.setContestLogo(item.getContestLogo());
                    tournamentList.add(tournamentListDto);
                });
                item.setTournamentList(tournamentList);
            }
        });

        return new TableDataInfo(collect, newContestListVOList.size());
    }


    private Long playerAudit(CoachOrPlayerAuditDTO param) {
        BMPayment payment = bmPaymentMapper.selectByObjectId(param.getId(), BMPayObjectTypeEnum.PLAYER.getCode());
        if (!Objects.equals(payment.getPaymentStatus(), PaymentStatusEnum.PAID.getId())) {
            throw new RuntimeException("该订单支付状态异常,请勿重复操作!");
        }
        BMPlayer player = bmPlayerMapper.selectById(param.getId());
        if (Objects.isNull(player)) {
            throw new RuntimeException("审核球员不存在");
        }
        //通过
        if (Objects.equals(1, param.getStatus())) {
            BaseBasketballTeam baseBasketballTeam1 = baseBasketballTeamMapper.selectByBmTeamId(player.getTeamId());
            if (Objects.isNull(baseBasketballTeam1)) {
                BMTeam bmTeam = bmTeamMapper.selectById(player.getTeamId());
                //同步球队
                BaseBasketballTeam baseBasketballTeam = new BaseBasketballTeam();
                baseBasketballTeam.setTeamName(bmTeam.getName());
                baseBasketballTeam.setTeamLogo(bmTeam.getLogo());
                baseBasketballTeam.setLeagueId(bmTeam.getContestId());
                baseBasketballTeam.setCreateUserId(bmTeam.getCreateUserId());
                baseBasketballTeam.setUpdateUserId(bmTeam.getCreateUserId());
                baseBasketballTeam.setCreateUserName(bmTeam.getCreateUserName());
                baseBasketballTeam.setUpdateUserName(bmTeam.getCreateUserName());
                baseBasketballTeam.setCreateTime(DateUtils.getNowDate());
                baseBasketballTeam.setBmTeamId(player.getTeamId());
                baseBasketballTeamMapper.insert(baseBasketballTeam);

                baseBasketballTeam1 = new BaseBasketballTeam();
                baseBasketballTeam1.setId(baseBasketballTeam.getId());
                baseBasketballTeam1.setLeagueId(baseBasketballTeam.getLeagueId());
            }
            //同步球员
            BaseBasketballPlayer basePlayer = new BaseBasketballPlayer();
            basePlayer.setName(player.getName());
            basePlayer.setState(0l);
            basePlayer.setProfilePicture(player.getLogo());
            basePlayer.setPlayerNumber(player.getPlayerNumber());
            basePlayer.setIsUp(0);
            basePlayer.setDocumentType(1l);
            basePlayer.setDocumentNumber(player.getCard());
            basePlayer.setCreateUserId(player.getCreateUserId());
            basePlayer.setUpdateUserId(player.getCreateUserId());
            basePlayer.setCreateUserName(player.getCreateUserName());
            basePlayer.setUpdateUserName(player.getCreateUserName());
            basePlayer.setCreateTime(DateUtils.getNowDate());
            baseBasketballPlayerMapper.insert(basePlayer);

            player.setAddFlag(1);
            bmPlayerMapper.updateById(player);

            //同步 球员球队关联表
            BasketballPlayerAndTeam playerAndTeam = new BasketballPlayerAndTeam();
            playerAndTeam.setPlayerId(basePlayer.getId());
            playerAndTeam.setTeamId(baseBasketballTeam1.getId());
            playerAndTeam.setType(0l);
            playerAndTeam.setContestId(baseBasketballTeam1.getLeagueId());
            playerAndTeam.setCreateUserId(basePlayer.getCreateUserId());
            playerAndTeam.setCreateUserName(basePlayer.getCreateUserName());
            basketballPlayerAndTeamMapper.insertBasketballPlayerAndTeam(playerAndTeam);

            return player.getTeamId();
        } else {
            //拒绝
            wxPayService.applyWxRefund(payment.getId());
        }

        return player.getTeamId();
    }


    private Long coachAudit(CoachOrPlayerAuditDTO param) {
        BMPayment payment = bmPaymentMapper.selectByObjectId(param.getId(), BMPayObjectTypeEnum.COACH.getCode());
        if (!Objects.equals(payment.getPaymentStatus(), PaymentStatusEnum.PAID.getId())) {
            throw new RuntimeException("该订单已审核,请勿重复操作!");
        }
        BMCoach coach = bmCoachMapper.selectById(param.getId());
        if (Objects.isNull(coach)) {
            throw new RuntimeException("审核教练不存在");
        }
        //通过
        if (Objects.equals(1, param.getStatus())) {
            BaseBasketballTeam baseBasketballTeam1 = baseBasketballTeamMapper.selectByBmTeamId(coach.getTeamId());
            if (Objects.isNull(baseBasketballTeam1)) {
                BMTeam bmTeam = bmTeamMapper.selectById(coach.getTeamId());
                //同步球队
                BaseBasketballTeam baseBasketballTeam = new BaseBasketballTeam();
                baseBasketballTeam.setTeamName(bmTeam.getName());
                baseBasketballTeam.setTeamLogo(bmTeam.getLogo());
                baseBasketballTeam.setLeagueId(bmTeam.getContestId());
                baseBasketballTeam.setCreateUserId(bmTeam.getCreateUserId());
                baseBasketballTeam.setUpdateUserId(bmTeam.getCreateUserId());
                baseBasketballTeam.setCreateUserName(bmTeam.getCreateUserName());
                baseBasketballTeam.setUpdateUserName(bmTeam.getCreateUserName());
                baseBasketballTeam.setCreateTime(DateUtils.getNowDate());
                baseBasketballTeam.setBmTeamId(coach.getTeamId());
                baseBasketballTeamMapper.insert(baseBasketballTeam);

                baseBasketballTeam1 = new BaseBasketballTeam();
                baseBasketballTeam1.setId(baseBasketballTeam.getId());
                baseBasketballTeam1.setLeagueId(baseBasketballTeam.getLeagueId());
            }
            //同步教练
            BaseCoach baseCoach = new BaseCoach();
            baseCoach.setName(coach.getName());
            baseCoach.setCoachPhoto(coach.getLogo());
            baseCoach.setType(Objects.equals(coach.getType(), 0) ? 1l : 2l);
            baseCoach.setDocumentNumber(coach.getCard());
            baseCoach.setDocumentType(1l);
            baseCoach.setCreateUserId(coach.getCreateUserId());
            baseCoach.setUpdateUserId(coach.getCreateUserId());
            baseCoach.setCreateUserName(coach.getCreateUserName());
            baseCoach.setUpdateUserName(coach.getCreateUserName());
            baseCoach.setCreateTime(DateUtils.getNowDate());
            baseCoachMapper.insert(baseCoach);

            coach.setAddFlag(1);
            bmCoachMapper.updateById(coach);

            //同步 球员球队关联表
            BasketballPlayerAndTeam playerAndTeam = new BasketballPlayerAndTeam();
            playerAndTeam.setPlayerId(baseCoach.getId());
            playerAndTeam.setTeamId(baseBasketballTeam1.getId());
            playerAndTeam.setType(1l);
            playerAndTeam.setContestId(baseBasketballTeam1.getLeagueId());
            playerAndTeam.setCreateUserId(baseCoach.getCreateUserId());
            playerAndTeam.setCreateUserName(baseCoach.getCreateUserName());
            basketballPlayerAndTeamMapper.insertBasketballPlayerAndTeam(playerAndTeam);
            return coach.getTeamId();
        }
        //拒绝
        if (Objects.equals(2, param.getStatus())) {
            wxPayService.applyWxRefund(payment.getId());
        }

        return coach.getTeamId();
    }
}
